package com.bestcem.xm.member.handler.imports;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.member.constant.ExcelFieldConstants;
import com.bestcem.xm.member.entity.mongo.ExtendFieldValue;
import com.bestcem.xm.member.util.CheckUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 导入excel所需要的公共方法
 *
 * @author yf.wang <yf.wang@idiaoyan.com>
 * @version V1.0
 * @date 2021/8/21
 */
@Slf4j
public class ImportExcelUtil {
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy/M/d");

    /**
     * 平年
     */
    public static final Map<String, Integer> ORDINARY_YEAR_MAP = new HashMap<String, Integer>() {{
        put("1", 31);
        put("3", 31);
        put("5", 31);
        put("7", 31);
        put("8", 31);
        put("10", 31);
        put("12", 31);
        put("4", 30);
        put("6", 30);
        put("9", 30);
        put("11", 30);
        put("2", 28);
    }};

    /**
     * 闰年
     */
    public static final Map<String, Integer> LEAP_YEAR_MAP = new HashMap<String, Integer>() {{
        put("1", 31);
        put("3", 31);
        put("5", 31);
        put("7", 31);
        put("8", 31);
        put("10", 31);
        put("12", 31);
        put("4", 30);
        put("6", 30);
        put("9", 30);
        put("11", 30);
        put("2", 29);
    }};

    /**
     * 判断是否更新 String
     *
     * @param inputValue
     * @param exitValue
     * @return
     */
    public static String dealUpdateFieldByString(String inputValue, String exitValue,
                                                 Boolean existedUpdate, Boolean nullUpdate) {
        if (StrUtil.isNotEmpty(inputValue)) {
            if (existedUpdate) {
                return inputValue;
            }
        } else {
            if (nullUpdate) {
                return inputValue;
            }
        }
        return exitValue;
    }

    /**
     * 判断是否更新 ObjectId
     *
     * @param inputValue
     * @param exitValue
     * @return
     */
    public static ObjectId dealUpdateFieldByObjectId(ObjectId inputValue, ObjectId exitValue,
                                                     Boolean existedUpdate, Boolean nullUpdate) {
        if (ObjectUtil.isNotEmpty(inputValue)) {
            if (existedUpdate) {
                return inputValue;
            }
        } else {
            if (nullUpdate) {
                return inputValue;
            }
        }
        return exitValue;
    }

    /**
     * 判断是否更新 Integer
     *
     * @param inputValue
     * @param exitValue
     * @return
     */
    public static Integer dealUpdateFieldByInteger(Integer inputValue, Integer exitValue,
                                                   Boolean existedUpdate, Boolean nullUpdate) {
        if (ObjectUtil.isNotEmpty(inputValue)) {
            if (existedUpdate) {
                return inputValue;
            }
        } else {
            if (nullUpdate) {
                return inputValue;
            }
        }
        return exitValue;
    }

    /**
     * 判断是否更新 Long
     *
     * @param inputValue
     * @param exitValue
     * @return
     */
    public static Long dealUpdateFieldByLong(Long inputValue, Long exitValue,
                                             Boolean existedUpdate, Boolean nullUpdate) {
        if (ObjectUtil.isNotEmpty(inputValue)) {
            if (existedUpdate) {
                return inputValue;
            }
        } else {
            if (nullUpdate) {
                return inputValue;
            }
        }
        return exitValue;
    }

    /**
     * 判断是否更新 date
     *
     * @param inputValue
     * @param exitValue
     * @return
     */
    public static Date dealUpdateFieldByDate(String inputValue, Date exitValue,
                                             Boolean existedUpdate, Boolean nullUpdate) {
        if (StrUtil.isNotEmpty(inputValue)) {
            if (existedUpdate) {
                return DateUtil.convertStringToDate(inputValue, "yyyy/M/d");
            }
        } else {
            if (nullUpdate) {
                return null;
            }
        }
        return exitValue;
    }

    /**
     * 对比字段 list
     *
     * @param inputValue
     * @param exitValue
     * @return
     */
    public static List<String> dealUpdateFieldByList(JSONArray inputValue, List<String> exitValue,
                                                     Boolean existedUpdate, Boolean nullUpdate) {
        if (ObjectUtil.isNotEmpty(inputValue)) {
            if (existedUpdate) {
                return inputValue.toJavaList(String.class);
            }
        } else {
            if (nullUpdate) {
                return inputValue.toJavaList(String.class);
            }
        }
        return exitValue;
    }

    /**
     * 构建数据
     *
     * @param data
     * @return
     */
    public static JSONObject buildMemberJson(Map<Integer, String> data,
                                             List<String> headers,
                                             Map<String, String> fieldNameMap) {
        JSONObject memberJson = new JSONObject();
        JSONArray address = new JSONArray();
        Boolean isAddress = true;
        for (int i = 0; i < headers.size(); i++) {
            String headName = headers.get(i);
            String value = data.get(i);
            if (StrUtil.isEmpty(value)) {
                // excel中不填的话读取为null 需要转化为""
                value = "";
            }
            if (log.isInfoEnabled()) {
                log.info("{} {}", headName, value);
            }
            if (fieldNameMap.containsKey(headName)) {
                // 基础字段（除 地址相关）
                String field = fieldNameMap.get(headName);
                if (field.equals(ExcelFieldConstants.BIRTHDAY)) {
                    // 如果存在出生日期。则根据出生日期计算年龄
                    if (StrUtil.isNotEmpty(value)) {
                        ServiceResult<String> result = CheckUtil.checkDateTimeFormat(value, "yyyy/M/d");
                        if (result.isSuccess()) {
                            // 只有日期格式正确才计算年龄
                            memberJson.put("年龄", DateUtil.ageOfNow(value));
                        } else {
                            memberJson.put("年龄", "");
                        }
                    } else {
                        // 否则 年龄为 空
                        memberJson.put("年龄", "");
                    }
                }
                memberJson.put(field, value);
            } else {
                // 除基础字段之外的字段
                memberJson.put(headName, value);
            }
        }
        return memberJson;
    }


    /**
     * 构建 扩展字段
     *
     * @param var
     * @return
     */
    public static ExtendFieldValue buildExtendValue(ExtendFieldValue var) {
        ExtendFieldValue extendFieldValue = new ExtendFieldValue();
        extendFieldValue.setFieldId(var.getFieldId());
        extendFieldValue.setFieldName(var.getFieldName());
        extendFieldValue.setFieldType(var.getFieldType());
        extendFieldValue.setFieldValue(var.getFieldValue());
        return extendFieldValue;
    }

    /**
     * 检查导入的时候日期是否合法 目前只针对 yyyy/M/d 格式的检查
     *
     * @param dateStr
     * @return
     */
    public static Boolean checkDateValue(String dateStr) {
        if (StrUtil.isBlank(dateStr)) {
            // 空值不检查
            return true;
        }

        try {
            LocalDate.parse(dateStr, DATE_FORMATTER);
        } catch (DateTimeParseException e) {
            return false;
        }
        return true;
//        String[] split = dateStr.split("/");
//        // 获取年份
//        String year = split[0];
//        // 获取月份
//        String month = split[1];
//        // 获取日期
//        String day = split[2];
//        int num = Integer.parseInt(day);
//        if (cn.hutool.core.date.DateUtil.isLeapYear(Integer.valueOf(year))) {
//            // 闰年
//            if (LEAP_YEAR_MAP.containsKey(month) && LEAP_YEAR_MAP.get(month) >= num) {
//                return true;
//            }
//        } else {
//            // 平年
//            if (ORDINARY_YEAR_MAP.containsKey(month) && LEAP_YEAR_MAP.get(month) >= num) {
//                return true;
//            }
//        }
//        return false;
    }

    /**
     * 检查数字 长度不超过9位
     *
     * @param num
     * @return
     */
    public static Boolean checkNumValue(String num) {
        if (StrUtil.isBlank(num)) {
            // 空值不检查
            return true;
        }
        if (num.length() > 9) {
            return false;
        }
        return true;

    }

    /**
     * 获取地址信息
     *
     * @param memberJson
     * @return
     */
    public static JSONArray getAddress(JSONObject memberJson) {
        if (memberJson == null) {
            return null;
        }
        // 省份
        String province = memberJson.getString(ExcelFieldConstants.PROVINCE);
        // 城市
        String city = memberJson.getString(ExcelFieldConstants.CITY);
        // 区县
        String district = memberJson.getString(ExcelFieldConstants.DISTRICT);
        // 街道
        String street = memberJson.getString(ExcelFieldConstants.STREET);
        if (!StringUtils.isAllBlank(province, city, district, street)) {
            JSONArray address = new JSONArray();
            // 不全为空
            address.add(province);
            address.add(city);
            address.add(district);
            address.add(street);
            return address;
        }
        return null;
    }

}
